load-use 数据冒险
如果 load 指令与其后紧邻的运算类指令存在数据相关问题, 则无法通过转发技术来解决。对于 load-use 数据冒险, 最简单的做法是由编译器在 add 指令之前插入一条 nop 指令。
load r2, 12(r1) # M[(r1)+12]->(r2)
add r4,r3,r2 # (r3)+(r2)->(r4)
例如上述指令就会出现该错误。add 指令进入 EX 阶段的前提是 load 指令的访存阶段(MEM)阶段结束。
转发技术的基本原理是将运算结果直接从一个流水线阶段传递到需要使用该结果的另一个指令的相应阶段,而无需等到结果写回寄存器。
然而,在加载-使用数据冒险中:
LOAD指令的数据在 MEM 阶段 才从内存加载到寄存器 R1。ADD指令在 EX 阶段 需要使用 R 1 的值,但此时LOAD指令尚未完成 MEM 阶段,R 1 中的数据还未更新完成。- 因此,
ADD指令在执行阶段无法获取到LOAD指令刚加载的数据,即使有转发路径,也没有在合适的时间点完成数据传递。

我们可以直接延迟一个机器周期,然后将 load 指令的 MEM 的结果直接传输给 add 指令。
最好的办法是预防,即在编译的时候由编译程序来尽量避免这种指令序列的出现。